package net.avcompris.jaxen.yaml;

import static com.avcompris.util.ExceptionUtils.nonNullArgument;
import static net.avcompris.jaxen.yaml.YamlXPath.NamespaceURI.XMLNSURI_AVC_BINDING_YAML;

import java.util.Iterator;

import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;

import net.avcompris.binding.BindConfiguration;
import net.avcompris.binding.impl.BinderXPathVariableResolver;

import org.jaxen.BaseXPath;
import org.jaxen.JaxenException;
import org.jaxen.UnresolvableException;
import org.jaxen.VariableContext;

import com.avcompris.common.annotation.Nullable;

public class YamlXPath extends BaseXPath {

	/**
	 * for, er... serialization?!#WTF
	 */
	private static final long serialVersionUID = 9106028393861473716L;

	public YamlXPath(
			final Object rootNode,
			final String xpathExpression,
			@Nullable final NamespaceContext nsContext,
			@Nullable final BinderXPathVariableResolver resolver,
			final BindConfiguration configuration) throws JaxenException {

		super(nonNullArgument(xpathExpression, "xpathExpression"),
				new YamlDocumentNavigator(rootNode, nsContext, configuration));
		
		if (nsContext != null) {

			final String uri = XMLNSURI_AVC_BINDING_YAML.getURI();

			for (final Iterator<?> it = nsContext.getPrefixes(uri); it
					.hasNext();) {

				final String prefix = (String) it.next();

				addNamespace(prefix, uri);
			}
		}

		if (resolver != null) {

			setVariableContext(new VariableContext() {

				@Override
				public Object getVariableValue(final String namespaceURI,
						final String prefix, final String localName) throws UnresolvableException {

					final QName variableName = new QName(namespaceURI,
							localName);

					return resolver.resolveVariable(variableName);
				}
			});
		}
	}

	//	@Override
	//	public Context getContext(final Object node) {
	//
	//		final Context context = super.getContext(node);
	//
	//		System.out.println("Context for: " + node);
	//		System.out.println("Context: " + context);
	//
	//		final Navigator n = context.getNavigator();
	//
	//		System.out.println("Navigator: " + n);
	//
	//		return context;
	//	}

	public static enum NamespaceURI {

		XMLNSURI_AVC_BINDING_YAML("http://avc-binding-yaml.googlecode.com/");

		public String getURI() {

			return uri;
		}

		private NamespaceURI(final String uri) {

			this.uri = nonNullArgument(uri, "uri");
		}

		private final String uri;
	}
}
